package com.navinfo.tripanalysis.common.arithmetic;

import com.navinfo.tripanalysis.common.arithmetic.common.CommonData;
import com.navinfo.tripanalysis.common.arithmetic.common.OuterEventData;
import com.navinfo.tripanalysis.common.arithmetic.common.OuterStatisticData;
import com.navinfo.tripanalysis.common.arithmetic.convert.EventDataConvert;
import com.navinfo.tripanalysis.common.arithmetic.custom.VarFuelLeakLocation_0200;
import com.navinfo.tripanalysis.common.arithmetic.enums.EventType;
import com.navinfo.tripanalysis.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.tripanalysis.common.config.ConfigMap;
import com.navinfo.tripanalysis.common.fuelleak.FuelLeakLocation;

import java.util.Optional;

/**
 * 实时计算：单独0200算法链的漏油高发地停留算法<br/>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 输出：事件<br/>
 * @author CAI.HS
 */
public class FuelLeakLocation_0200 extends AbstractArithmetic<VarFuelLeakLocation_0200> {
    /**
     * 事件类型
     */
    private static final EventType EVENT_TYPE = EventType.fuleLeakLocation_0200;
    /**
     * 经过漏油高发地(0200) 停车熄火时  时长阈值 单位ms
     */
    private long flameoutTimeThreshold = ConfigMap.getLong("0200_FuelLeakLocation_Flameout_Time");
    /**
     * 经过漏油高发地(0200) 停车怠速时  时长阈值 单位ms
     */
    private long idleTimeThreshold = ConfigMap.getLong("0200_FuelLeakLocation_Idle_Time");

    /**
     * 是否停车
     * @param data
     * @return
     */
    private boolean isParking(CommonData data){
        return !data.isAccStatus() || (data.getSpeedKmh()==0 && data.isAccStatus());
    }

    @Override
    public void calculate() {
        logger.debug("进入0200漏油高发地停留算法[terminalId:{}]", terminalId);
        VarFuelLeakLocation_0200 var = getObj();
        CommonData commonData = getCommonData();
        
        boolean isParking = isParking(commonData);

        //记录停车开始点状态，1：停车怠速 2：停车熄火
        if(isParking && !var.isPreFuelLeak()){
            var.setStatus(commonData.isAccStatus() ? 1 : 2);
        }

        FuelLeakLocation fuelLeakLocation = isParking ?  drivingData.getFuelLeakLocation() : null;

        // 上一点是否是漏油点
        boolean preInDangerLocation = var.isPreFuelLeak();
        // 当前位置是否是漏油点
        boolean curInDangerLocation = fuelLeakLocation != null;

        //算法计算
        switch (super.getEventStatus(preInDangerLocation, curInDangerLocation)) {
            case START:
                logger.debug("漏油高发地停留，事件开始.[terminalId:{}]", terminalId);
                OuterEventData eventData = startEventData(EVENT_TYPE);
                // 事件开始记录，满足时长阈值后才推送
                // 当前为了不推送，暂时将状态设置成S_STATUS_FINISHED
                eventData.setStatus(OuterEventData.S_STATUS_FINISHED);
                eventData.setExtendField01(var.getStatus());// 1：怠速 2：停车
                eventData.setExtendField02(fuelLeakLocation.getLat());// 漏油点经度
                eventData.setExtendField03(fuelLeakLocation.getLon());// 漏油点纬度
                eventData.setExtendField09(fuelLeakLocation.getTile_id()); // 瓦片ID
                eventData.setExtendField10(fuelLeakLocation.getEvent_cnt());   // 次数
                break;
            case IN:
                logger.debug("漏油高发地停留，事件中.[terminalId:{}]", terminalId);
                calcEventData(EVENT_TYPE);
                break;
            case END:
                logger.debug("漏油高发地停留，事件结束.[terminalId:{}]", terminalId);
                calcEventData(EVENT_TYPE);
                endEvent();
                break;
            default:
                logger.debug("漏油高发地停留，上一次和本次都未经过，跳出算法.[terminalId:{}]", terminalId);
        }

        var.setPreFuelLeak(curInDangerLocation);

        logger.debug("离开漏油高发地停留算法[terminalId:{}]", terminalId);
    }


    /**
     * 累加事件信息
     */
    @Override
    public void calcEventData(EventType eventType) {
        Optional.ofNullable(drivingData.getEventData(eventType)).ifPresent(eventData -> {
            eventData.setExtendField04(Optional.ofNullable(eventData.getExtendField04()).orElse(0) + getCommonData().getDffTime());
            logger.debug("事件累计时长：{}",eventData.getExtendField04());

            if (eventData.getStatus() == OuterEventData.S_STATUS_FINISHED) {
                // 停车怠速时长阈值
                if(eventData.getExtendField01()==1 && eventData.getExtendField04()>=idleTimeThreshold){
                    // 满足时长阈值后，需要推送事件开始，将状态设置成null
                    eventData.setStatus(0);
                    logger.debug("怠速事件输出：时长：{},阈值：{}",eventData.getExtendField04(), idleTimeThreshold);

                }
                // 停车熄火时长阈值
                if(eventData.getExtendField01()==2 && eventData.getExtendField04()>=flameoutTimeThreshold){
                    // 满足时长阈值后，需要推送事件开始，将状态设置成null
                    eventData.setStatus(0);
                    logger.debug("停车事件输出：时长：{},阈值：{}",eventData.getExtendField04(), flameoutTimeThreshold);

                }
            }
        });
    }

    /**
     * 结束事件
     */
    private void endEvent() {
        Optional.ofNullable(drivingData.getEventData(EVENT_TYPE)).ifPresent(eventData -> {
            // 删除map中事件缓存
            drivingData.removeEventData(EVENT_TYPE);

            if(!isOutputEvent()) return;

            // 输出事件
            EventDataConvert.convertEnd(eventData, drivingData);

            // 持续时长 > 时长阈值
            if(eventData.getExtendField01()==1 && eventData.getDuration()>=idleTimeThreshold){
                // 怠速时长阈值
                drivingData.addEventDataToList(eventData);
            } else if(eventData.getExtendField01()==2 && eventData.getDuration()>=flameoutTimeThreshold){
                // 停车熄火时长阈值
                drivingData.addEventDataToList(eventData);
            } else {
                logger.debug("时间{}ms,小于阈值{}ms，不进行统计", eventData.getDuration());
            }
        });
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
    }
}
